package main

import (
	"fmt"
	"io/ioutil"
	"math"
	"reflect"
	"runtime"
)

// switch
// switch 自动break, 除非使用fallthrough
func eval(a, b int, op string) int {
	var result int
	switch op {
	case "+":
		result = a + b
	case "-":
		result = a - b
	case "*":
		result = a * b
	case "/":
		result = a / b
	default:
		panic("unsupported operator: " + op)
	}
	//fmt.Println(result)
	/*
		todo: switch会自动break, 除非使用fallthrough
		panic 报错
	*/
	return result
}

func grade(score int) string {
	g := ""
	switch {
	case score < 0 || score > 100:
		panic(fmt.Sprintf("Wrong score: %d", score))
	case score < 60:
		g = "F"
	case score < 80:
		g = "C"
	case score < 90:
		g = "B"
	case score <= 100:
		g = "A"
	default:
		panic(fmt.Sprintf("Wrong score: %d", score))
	}
	return g
}

func apply(op func(int, int) int, a, b int) int { // 函数作为参数
	p := reflect.ValueOf(op).Pointer()
	opName := runtime.FuncForPC(p).Name()
	fmt.Println("Calling function %s with args (%d, %d)", opName, a, b)
	return op(a, b)
}

func sum(numbers ...int) int { //可变参数
	s := 0
	for i := range numbers {
		s += numbers[i]
	}
	return s
}

func swap(a, b *int) {
	*a, *b = *b, *a
}

func main() {
	const filename = "abc.txt"
	// if 一
	contents1, err := ioutil.ReadFile(filename) //读取文件
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Printf("%s\n", contents1)
	}
	// if 第二种写法 在条件中赋值
	if contents2, err := ioutil.ReadFile(filename); err != nil {
		fmt.Println(err)
	} else {
		fmt.Printf("%s\n", contents2)
	}
	fmt.Printf("%s\n", contents1) // contents2不能打印, 生存周期只在if中
	/*todo:
	1. if的条件里可以赋值
	2. if的条件里赋值的变量作用域就在这个if语句中
	*/

	r := eval(2, 3, "-")
	fmt.Println(r)
	fmt.Println(
		grade(22),
		grade(77),
		grade(88),
		grade(99),
	)

	fmt.Println(apply(
		func(a int, b int) int {
			return int(math.Pow(float64(a), float64(b)))
		}, 3, 4,
	))

	fmt.Println(sum(1, 2, 4, 5, 6, 7, 4))

	var a int = 2
	var pa *int = &a
	*pa = 3
	fmt.Println(a)
	var b = 4
	swap(pa, &b)
	fmt.Println(a, b, &a, &b)
}
